class User < ActiveRecord::Base
  rolify
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable,
         :authentication_keys => [:login]

  has_many :user_confirms, :dependent => :delete_all
  has_many :humble_site, :dependent => :destroy
  belongs_to :public_confirm, :class_name => "UserConfirm"

  validates_presence_of :email
  validates_uniqueness_of :email, :case_sensitive => false

  validates_presence_of :username
  validates_uniqueness_of :username, :case_sensitive => false

  attr_accessor :login 
  
  has_attached_file :avatar, styles: { medium: "300x300>", thumb: "100x100>" }, default_url: "/images/:style/missing.png"
  validates_attachment_content_type :avatar, content_type: /\Aimage\/.*\Z/

  after_create :add_user_roles,:make_default_confirm,:add_default_avatar
  after_initialize :create_login, :if => :new_record?
  before_create :add_token
  
  #自动填充用户名
  def create_login
    if self.username.blank?
      email = self.email.split(/@/)
      login_taken = User.where(:username => email[0]).first
      unless login_taken
        self.username = email[0]
      else
        self.username = self.email
      end
    end
  end

  #创建头像
  
  def add_default_avatar
    rand_num = rand(0..55)
    url =  Dir.pwd + "/app/assets/images/default_avatar/portrait_#{rand_num}.jpg"
    file = File.open(url)
    self.avatar = file
    avatar = self.save!
    if avatar 
      self.public_confirm.image_default = self.avatar.url(:thumb)
      self.public_confirm.save
    end
  end

  #激活账户后--自动添加基础权限
  def add_user_roles
    role = self.add_role "user"
    RolesPermission.find_or_create_by(:role_id => role.id, :action_name => "read", :description=> "读取")
  end

  class ActivationCodeNotFound < StandardError; end

  class AlreadyActivated < StandardError
    attr_reader :user, :message
    def initialize(user, message=nil)
      @message, @user = message, user
    end
  end

  # Finds the user with the corresponding activation code, activates their user and returns the user.
  #
  # Raises:
  # [user::ActivationCodeNotFound] if there is no user with the corresponding activation code
  # [user::AlreadyActivated] if the user with the corresponding activation code has already activated their user
  def self.find_and_activate!(activation_code)
    raise ArgumentError if activation_code.nil?
    user = find_by(:activation_code => activation_code)
    raise ActivationCodeNotFound unless user
    raise AlreadyActivated.new(user) if user.active?
    user.send(:activate!)
    user
  end

  # 返回随机字符
  def make_activation_code(user)
    if user.activation_code.blank?
        user.activation_code = User.get_num_token
        #Digest::SHA1.hexdigest( Time.now.to_s.split(//).sort_by {rand}.join )
    end
    user.save!
  end
  
  # 发送激活邮件
  def send_web_active_mail
    if self.email.split(/@/)[1] != "openid.com"
        make_activation_code(self)
      begin
        umail = UserMailer.verification_email(self).deliver
      rescue
      end
    else
      self.save!
    end
  end
  
  
  def make_default_confirm
    begin
      self.public_confirm = self.user_confirms.build(:title => "标准信息", :email => self.email)
      self.public_confirm.deletable = false
      if public_confirm.save!
        send_web_active_mail
      end
    rescue 
      Rails.logger.info("===创建账号错误===")
    end
  end

  def self.find_first_by_auth_conditions(warden_conditions)
    conditions = warden_conditions.dup
    if login = conditions.delete(:login)
      where(conditions).where(["lower(username) = :value OR lower(email) = :value", { :value => login.downcase }]).first
    else
      if conditions[:username].nil?
        where(conditions).first
      else
        where(username: conditions[:username]).first
      end
    end
  end

  def login=(login)
    @login = login
  end

  def login
    @login || self.username || self.email
  end

  def active?
    activation_code.blank?
  end

  # The existence of an activation code means they have not activated yet

  def activate!
    @activated = true
    self.activated_at = Time.now.utc
    self.activation_code = nil
    self.save
  end

  # First update the password_reset_code before setting the
  # reset_password flag to avoid duplicate email notifications.

  def disable!
    update_attribute(:enabled, false)
  end
  
  def self.get_num_token
    loop do
      token = ('0'..'9').to_a.shuffle[0..5].join 
      unless User.where(authentication_token: token).first
        break token
      end
    end
  end
  
  def self.get_token
    loop do
      token = Devise.friendly_token
      unless User.where(authentication_token: token).first
        break token
      end
    end
  end
  
private
  def add_token
    self.authentication_token = ensure_authentication_token
  end
  #自动生成Token
  def ensure_authentication_token
    self.authentication_token ||= generate_authentication_token
  end

  def generate_authentication_token
    loop do
      token = Devise.friendly_token
      unless User.where(authentication_token: token).first
        break token
      end
    end
  end
end
